using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace BizTalkCop.Rules.Naming
{
    /// <summary>
    /// Helper class for member names
    /// </summary>
    public static class MemberName
    {

        #region Private static fields

        private static Regex pascalRegex;
        private static Regex camelRegex;
        private static Regex generatedNameRegex;

        #endregion

        #region Private static properties

        private static Regex PascalRegex
        {
            get
            {
                if (pascalRegex == null)
                {
                    pascalRegex = new Regex(RegexPattern.PascalCase, RegexOptions.Compiled);
                }
                return pascalRegex;
            }
        }
        
        private static Regex CamelRegex
        {
            get
            {
                if (camelRegex == null)
                {
                    camelRegex = new Regex(RegexPattern.CamelCase, RegexOptions.Compiled);
                }
                return camelRegex;
            }
        }
        
        private static Regex GeneratedNameRegex
        {
            get
            {
                if (generatedNameRegex == null)
                {
                    generatedNameRegex = new Regex(RegexPattern.GeneratedName, RegexOptions.Compiled);
                }
                return generatedNameRegex;
            }
        }

        #endregion

        #region Public static methods

        /// <summary>
        /// Returns whether the given name is Pascal cased
        /// </summary>
        /// <param name="name">Name to check</param>
        /// <returns>Whether name is Pascal cased</returns>
        public static bool IsPascalCase(string name)
        {
            return PascalRegex.IsMatch(name);
        }

        /// <summary>
        /// Returns whether the given name is camel cased
        /// </summary>
        /// <param name="name">Name to check</param>
        /// <returns>Whether name is camel cased</returns>
        public static bool IsCamelCase(string name)
        {
            return CamelRegex.IsMatch(name);
        }

        /// <summary>
        /// Returns whether the given name is a BizTalk-generated name
        /// </summary>
        /// <param name="name">Name to check</param>
        /// <returns>Whether name id generated</returns>
        public static bool IsGeneratedName(string name)
        {
            return GeneratedNameRegex.IsMatch(name);
        }

        /// <summary>
        /// Returns the given name as Pascal case
        /// </summary>
        /// <param name="memberName">Name to convert</param>
        /// <returns>Name in Pascal case</returns>
        public static string ToPascalCase(string memberName)
        {
            //basic implementation, trims non-word characters and uppercases first character:
            memberName = Clean(memberName);
            return string.Concat(memberName[0].ToString().ToUpper(), memberName.Substring(1));
        }

        /// <summary>
        /// Returns the given name as camel case
        /// </summary>
        /// <param name="memberName">Name to convert</param>
        /// <returns>Name in camel case</returns>
        public static string ToCamelCase(string memberName)
        {
            //basic implementation, trims non-word characters and lowercases first character:
            memberName = Clean(memberName);
            return string.Concat(memberName[0].ToString().ToLower(), memberName.Substring(1));
        }

        /// <summary>
        /// Cleans the given name, stripping non-word characters
        /// </summary>
        /// <param name="memberName">Name</param>
        /// <returns>Cleaned name</returns>
        private static string Clean(string memberName)
        {
            return memberName.Replace("_", "");
        }

        #endregion

        #region Private structs

        private struct RegexPattern
        {
            public const string PascalCase = @"^[A-Z][a-zA-Z0-9]+(?<=.*[A-Z]+.*)(?<![A-Z]+)$";
            public const string CamelCase = @"^[a-z][a-zA-Z0-9]+(?<=.*[A-Z]+.*)$";
            public const string GeneratedName = @".*_[0-9]*.[0-9]*.[0-9]*.[0-9]*_.*_\w*";
        }

        #endregion
    }
}
